//
//  MMKVManager.swift
//  hrhtv
//
//  Created by Ink on 2025-04-27.
//

import MMKV

//// MARK: - 泛型持久化桥接类
//public class PersistenceManager<T>: ZMDataPersistence {
//    public let storeKey: String
//    public init(storeKey: String) { self.storeKey = storeKey }
//}
//
//extension PersistenceManager {
//    func save(_ value: T?) {
//        Self.set(value: value, forKey: storeKey)
//    }
//    func value() -> T? {
//        Self.value(forKey: storeKey)
//    }
//    func removeValue() {
//        Self.removeValue(forKey: storeKey)
//    }
//}
//
//protocol ZMDataPersistence {
//    associatedtype T
//    static func value(forKey key: String) -> T?
//    static func set(value: T?, forKey key: String)
//    static func removeValue(forKey key: String)
//}
//
//// MARK: - 默认实现（空实现）
//extension ZMDataPersistence {
//    static func value(forKey key: String) -> T? { nil }
//    static func set(value: T?, forKey key: String) {
//        print("msg")
//    }
//    static func removeValue(forKey key: String) { MMKVManager.removeValue(forKey: key) }
//}
//
//// MARK: - Codable 类型扩展
//extension ZMDataPersistence where T: Codable {
//    static func value(forKey key: String) -> T? {
//        MMKVManager.value(forKey: key)
//    }
//    static func set(value: T?, forKey key: String) {
//        MMKVManager.set(value: value, forKey: key)
//    }
//}
//
//extension ZMDataPersistence where T: Collection, T.Element: Codable, T: Codable {
//    static func value(forKey key: String) -> T? {
//        MMKVManager.value(forKey: key)
//    }
//
//    static func set(value: T?, forKey key: String) {
//        MMKVManager.set(value: value, forKey: key)
//    }
//}
//
//protocol ZMKeyDataPersistence {
//    associatedtype T
//    static var mmKey: String { get }
//    static func mmValue() -> T?
//    static func mmSet(value: T?)
//    static func mRemoveValue()
//}
//
//extension ZMKeyDataPersistence {
//    static func mmValue() -> T? { nil }
//    static func mmSet(value: T?) { }
//    static func mRemoveValue() { }
//}
//
//extension ZMKeyDataPersistence where Self: ZMDataPersistence {
//    static func mmValue() -> T? { return value(forKey: mmKey) }
//    static func mmSet(value: T?) { set(value: value, forKey: mmKey) }
//    static func mRemoveValue() { removeValue(forKey: mmKey) }
//}
//
//public struct MMKVManager {
//    
//    static var mmkv: MMKV = {
//        let dir = FileManager.documentPath.append(path: "MMKVStored")
//        MMKV.initialize(rootDir: dir)
//        return MMKV(mmapID: ZM_BUNDLEID) ?? MMKV()
//    }()
//    
//    @UserDefault(suiteName: StoreSuiteName, "MMKVManager.Keys")
//    public static var keys = [String]()
//    
//    public static func initialize() {
//        let _ = mmkv
//    }
//}
//
//public extension MMKVManager {
//    
//    static func add<T>(data: MMKVStored<T>) {
//        addKey(data.key)
//    }
//    
//    static func addKey(_ key: String) {
//        if keys.contains(key) != true {
//            keys.append(key)
//        }
//    }
//    
//    static func removeKey(_ key: String) {
//        keys.removeAll(where: { $0 == key })
//    }
//    
//    static func set<T: Encodable>(value: T?, forKey key: String) {
//        guard let value = value else {
//            removeValue(forKey: key)  // `nil` 时删除存储
//            return
//        }
//        if let data = try? JSONEncoder().encode(value) {
//            MMKVManager.set(data, forKey: key)
//            addKey(key)
//        }
//    }
//}

public protocol DataPersistable {
    associatedtype PersistedType: Codable
    
    static func set<T: Encodable>(_ value: T, forKey key: String)
    static func value<T: Decodable>(forKey key: String) -> T?
    static func removeValue(forKey key: String)
}

public extension DataPersistable {
    static func set<T: Encodable>(_ value: T, forKey key: String) {
        MMKVManager.set(value, forKey: key)
    }
    static func value<T: Decodable>(forKey key: String) -> T? {
        return MMKVManager.value(forKey: key)
    }
    static func removeValue(forKey key: String) {
        MMKVManager.removeValue(forKey: key)
    }
}

public final class PersistenceBridge<T: Codable> {
    let storageKey: String
    
    public init(storageKey: String) {
        self.storageKey = storageKey
    }
}

extension PersistenceBridge: DataPersistable {
    public typealias PersistedType = T
    
    public func save(_ value: T?) {
        Self.set(value, forKey: storageKey)
    }
    
    public func load() -> T? {
        Self.value(forKey: storageKey)
    }
    
    public func remove() {
        Self.removeValue(forKey: storageKey)
    }
}

public final class MMKVManager {
    public static let shared = MMKVManager()
    private lazy var storage: MMKV = {
        let dir = FileManager.documentPath.append(path: "MMKVStored")
        MMKV.initialize(rootDir: dir)
        return MMKV(mmapID: ZM_BUNDLEID) ?? MMKV()
    }()
    
    @UserDefault(suiteName: StoreSuiteName, "MMKVManager.Keys")
    public static var keys = [String]()
    
    public static func setup() {
        let _ = shared.storage
    }
    
    public static func storageSet(_ data: Data, forKey key: String) {
        shared.storage.set(data, forKey: key)
    }
    
    public static func storageGetData(forKey key: String) -> Data? {
        shared.storage.data(forKey: key)
    }
}

extension MMKVManager {
    
    // MARK: - Thread-Safe Operations
    func encodeAndSet<T: Encodable>(_ value: T, forKey key: String) {
        do {
            let data = try JSONEncoder().encode(value)
            MMKVManager.storageSet(data, forKey: key)
            MMKVManager.addKey(key)
        } catch {
            print("[MMKV] Encode failed for key: \(key)", error)
        }
    }
    
    func decodedValue<T: Decodable>(forKey key: String) -> T? {
        guard let data = MMKVManager.storageGetData(forKey: key) else { return nil }
        return try? JSONDecoder().decode(T.self, from: data)
    }
    
    func removeValue(forKey key: String) {
        storage.removeValue(forKey: key)
        Self.removeKey(key)
    }
}

public extension MMKVManager {
    
    static func add<T>(data: MMKVStored<T>) {
        addKey(data.key)
    }
    
    static func addKey(_ key: String) {
        if keys.contains(key) != true {
            keys.append(key)
        }
    }
    
    static func removeKey(_ key: String) {
        keys.removeAll(where: { $0 == key })
    }
    
    static func set<T: Encodable>(_ value: T, forKey key: String) {
        shared.encodeAndSet(value, forKey: key)
    }
    static func value<T: Decodable>(forKey key: String) -> T? {
        return shared.decodedValue(forKey: key)
    }
    static func removeValue(forKey key: String) {
        shared.removeValue(forKey: key)
    }
}

@propertyWrapper
public struct MMKVStored<T: Codable> {
        
    fileprivate let key: String
    fileprivate var defaultValue: T
    
    public init(wrappedValue: T, key: String) {
        self.key = key
        self.defaultValue = wrappedValue
    }
    
    public var getMMKey: String {
        return key
    }
    
    public var wrappedValue: T {
        get {
            
            guard let value: T = MMKVManager.value(forKey: key) else {
                let newDefault = createDefaultValueWithUpdatedDate()
                MMKVManager.set(newDefault, forKey: key)
                return newDefault
            }
            
            // 如果 value 符合 ExpireValidatable 协议，额外判断是否当天
            if let validatable = value as? ExpireValidatable {
                if validatable.isLive {
                    return value
                } else {
                    // 清理并返回默认值
                    MMKVManager.removeValue(forKey: key)
                    let newDefault = createDefaultValueWithUpdatedDate()
                    MMKVManager.set(newDefault, forKey: key)
                    return newDefault
                }
            }
            
            // 普通对象，直接返回
            return value
        }
        set {
            let value = deepUnwrap(newValue)
            if value.isNone {
                MMKVManager.removeValue(forKey: key)
            }
            else if let value = value as? Encodable {
                MMKVManager.set(value, forKey: key)
            }
        }
    }
    
    public var projectedValue: MMKVStored<T> { self }
    
    public func removeValue() {
        MMKVManager.removeValue(forKey: key)
    }
    
    // MARK: - 私有方法
    /// 创建带更新日期的默认值
    private func createDefaultValueWithUpdatedDate() -> T {
        guard var validatable = defaultValue as? ExpireValidatable else {
            return defaultValue
        }
        
        validatable.updateStoredDate()
        return validatable as? T ?? defaultValue
    }
}

/// 支持 options
public extension MMKVStored where T : ZMStoredKeyProtocol {
    init(wrappedValue: T) {
        self.init(wrappedValue: wrappedValue, key:T.ZMStoredKey)
    }
}

/// 支持 options
public extension MMKVStored where T : ExpressibleByNilLiteral {
    // 可选类型初始化器使用 ExpressibleByNilLiteral 约束
    init(wrappedValue: T = nil, key: String) {
        self.key = key
        self.defaultValue = wrappedValue
    }
}

/// 支持 options
public extension MMKVStored where T : ExpressibleByNilLiteral & ZMStoredKeyProtocol {
    // 可选类型初始化器使用 ExpressibleByNilLiteral 约束
    init(wrappedValue: T) {
        self.init(wrappedValue: wrappedValue, key:T.ZMStoredKey)
    }
}

public protocol ZMStoredKeyProtocol {
    static var ZMStoredKey: String { get }
}

public extension ZMStoredKeyProtocol where Self: ClassNameProtocol {
    static var ZMStoredKey: String { className }
}

// 失效协议
public protocol ExpireValidatable {
    var isLive: Bool { get }
    var zmStoredDate: Date { get set }
    var isSameDay: Bool { get }
    
    mutating func updateStoredDate()
}

public extension ExpireValidatable {
    @_disfavoredOverload
    var zmStoredDate: Date { get { Date() } set { } }
    var isSameDay: Bool { Calendar.current.isDate(zmStoredDate, inSameDayAs: Date()) }
    var isLive: Bool { isSameDay }
    
    mutating func updateStoredDate() {
        zmStoredDate = Date()
    }
}
